import { ComponentInternalInstance, UnwrapRef } from 'vue';
import { FormInstance, TableInstance } from 'element-plus';
import { cloneDeep } from 'lodash';

interface ListParams<T, P> {
  /**
   * 请求传参
   */
  params: T;
  /**
   * 新增弹窗的表单数据
   */
  initForm?: P;
  /**
   * 列表接口
   * @param arg
   * @returns
   */
  listApi: (...arg: any) => Promise<any>;
}

export const useList = <T, P>(listOptions: ListParams<T, P>) => {
  const tableRef = ref<TableInstance>(); // 表格的ref
  const queryFormRef = ref<FormInstance>(); // 搜索条件表单的ref
  const formRef = ref<FormInstance>(); // 弹窗表单的ref
  const loading = ref<boolean>(false); // v-loading的loading，一般用在table里面
  const showSearch = ref<boolean>(true); // 是否显示搜索区域
  const ids = ref<Array<number | string>>([]); // 表格可选择时，选中数据的id集合
  const single = ref<boolean>(true); // 表格可选择时，是否只选择了一项
  const multiple = ref<boolean>(true); // 表格可选择时，是否选择了多项项
  const open = ref<boolean>(false); // 弹窗的开关
  const title = ref<string>(''); // 弹窗标题
  const form = ref<P>(cloneDeep({ ...(listOptions.initForm as P) })); // 弹窗的数据
  const openType = ref<string>(''); // 弹窗打开类型 add /edit / detail
  const selections = ref<TableList['data'][number][]>([]); // 选择列表项集合
  // 表格数据
  type TableList = { data: any[]; total: number };
  const tableList = reactive<TableList>({
    data: [],
    total: 0
  });

  const copyParams = ref<T>(listOptions.params);
  type QueryParams = PageQuery & typeof copyParams.value;
  // 筛选条件
  const queryParams = ref<QueryParams>(
    Object.assign(
      {
        pageNum: 1,
        pageSize: 10
      },
      copyParams.value
    )
  );

  /**
   * 获取列表
   */
  async function getList() {
    loading.value = true;
    try {
      const { rows = [], data, total = 0 } = await listOptions.listApi(queryParams.value);
      tableList.data = data || rows;
      tableList.total = total;
    } catch (error) {
      console.error(error);
    } finally {
      loading.value = false;
    }
  }
  /**
   * 搜索
   */
  function handleQuery() {
    queryParams.value.pageNum = 1;
    getList();
  }
  /**
   * 弹窗表单重置
   */
  const reset = () => {
    form.value = cloneDeep(listOptions.initForm as UnwrapRef<P>);
    formRef.value?.resetFields();
  };

  /** 重置按钮操作，重置搜索条件 */
  const resetQuery = () => {
    queryFormRef.value?.resetFields();
    nextTick(() => {
      handleQuery();
    });
  };
  /** 弹窗取消按钮 */
  const cancel = () => {
    open.value = false;
    reset();
  };
  // proxy实例，调用main.ts中挂在到app上面的一系列方法
  const { proxy } = getCurrentInstance() as ComponentInternalInstance;

  return {
    tableRef,
    queryFormRef,
    formRef,
    proxy,
    queryParams,
    loading,
    tableList,
    showSearch,
    ids,
    single,
    multiple,
    open,
    title,
    form,
    getList,
    handleQuery,
    reset,
    resetQuery,
    cancel,
    openType,
    selections
  };
};
